#include "Game.h"
#include "Node.h"
#include "Mesh.h"
#include "Graphics.h"
#include "Application.h"
#include "Camera.h"
#include "Math.h"
#include "Scene.h"

#include "Square.h"
#include "Chessman.h"
#include "Player.h"

#include "UIText.h"

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

static Game* g_game = NULL;

Game* Game::GetGame()
{
	if (!g_game)
	{
		g_game = new Game();
	}
	return g_game;
}

Game::Game(void)
{
	mSelectedChessman = NULL;
	mGameScene = NULL;
	mGraphics = NULL;
}

Game::~Game(void)
{
}

bool Game::Init()
{
	mGraphics = Graphics::GetGraphics();

	mGameScene = new Scene();
	mGameScene->SetBackgroundColor(Color(0.5294f, 0.8078f, 0.9804f, 1.0f));

	mGraphics->SetScene(mGameScene);

	//camera->SetPosition(Vector3(-8, 4, 0));
	//camera->LookAt(Vector3(0, 4, 0));
	
	for (int i = 1; i <= 8; i++)
	{
		for (int j = 1; j <= 8; j++)
		{
			Square* square = new Square(i, j, (i + j) % 2 == 0 ? Square::COLOR_DARK : Square::COLOR_LIGHT);
			mGameObjects.push_back(square);
			mChessboard[i-1][j-1] = NULL;
		}
	}

	mGameScene->CreateText(150, 30, "START");
	mGameScene->CreateText(300, 30, "END");
	mTopButton = mGameScene->CreateText(110, 470, "BUILT BY CHENG XIE AND KUANGDA LI");

	mStarted = false;

	return true;
}

void Game::Start()
{
	ClearChessboard();

	mCurrentPlayer = PLAYER_ONE;

	mSelectedChessman = NULL;

	for (int j = 1; j <= 3; j++)
	{
		for (int i = 1; i <= 8; i++)
		{
			if ( (i+j)%2 == 0 ) 
			{
				Chessman* chessman = new Chessman(i, j, PLAYER_ONE);
				mChessboard[i-1][j-1] = chessman;
				mGameObjects.push_back(chessman);

				chessman = new Chessman(9 - i, 9 - j, PLAYER_TWO);
				mChessboard[8-i][8-j] = chessman;
				mGameObjects.push_back(chessman);
			}
		}
	}

	mStarted = true;
	mTopButton->SetText("BUILT BY CHENG XIE AND KUANGDA LI");
}

bool Game::Update( float dt )
{
	Camera* camera = mGraphics->GetCamera();

	static float yPos = 6.0f;
	float dy = dt * 6.0f;

	if (mCurrentPlayer == PLAYER_ONE)
	{
		if (yPos > 2)
		{
			yPos -= dy;
		}
		camera->SetPosition(Vector3(4, yPos, 7));
		camera->LookAt(Vector3(4, 4, 0));
	}
	else {
		if (yPos < 6)
		{
			yPos += dy;
		}
		camera->SetPosition(Vector3(4, yPos, 7));
		camera->LookAt(Vector3(4, 4, 0));
	}

	bool oneCanMove = false;
	bool twoCanMove = false;
	bool oneHaveChessman = false;
	bool twoHaveChessman = false;

	for (int i = 0; i < 8; i++)
	{
		for (int j = 0; j < 8; j++)
		{
			Chessman* chessman = mChessboard[i][j];
			if (chessman)
			{
				if (chessman->GetOwner() == PLAYER_ONE)
				{
					oneHaveChessman = true;
					if (chessman->GetLegalMoves(mChessboard).size())
					{
						oneCanMove = true;
					}
				}
				else
				{
					twoHaveChessman = true;
					if (chessman->GetLegalMoves(mChessboard).size())
					{
						twoCanMove = true;
					}
				}
			}
		}
	}

	if (mStarted && (!oneCanMove || !oneHaveChessman))
	{
		mCurrentPlayer = -1;
		mTopButton->SetText("PLAYER ONE WIN");
		mStarted = false;
	}

	if (mStarted && (!twoCanMove || !twoHaveChessman))
	{
		mCurrentPlayer = -1;
		mTopButton->SetText("PLAYER TWO WIN");
		mStarted = false;
	}

	return true;
}

bool Game::ProcessEvent( sf::Event event )
{
	if (event.Type == sf::Event::MouseButtonPressed)
	{
		int mouseX = event.MouseButton.X;
		int mouseY = event.MouseButton.Y;

		mouseY = mGraphics->GetWindow()->GetHeight() - mouseY - 1;

		Node* node = mGraphics->HitTest(mouseX, mouseY);

		if (node)
		{
			GameObject* object = GetGameObjectByNode(node);
			if (object)
			{
				object->OnSelect();
			}
		}

		UIText* text = mGraphics->UIHitTest(mouseX, mouseY);

		if (text)
		{
			string str = text->GetText();

			if (str == "START")
			{
				Start();
			}

			if (str == "END")
			{
				Application::GetApplication()->GetWindow()->Close();
			}
		}
	}

	return true;
}

Chessman* Game::GetChessmanAtPosition( int x, int y )
{
	return mChessboard[x-1][y-1];
}

void Game::ClearChessboard()
{	
	for (int i = 0; i < 8; i++)
	{
		for (int j = 0; j < 8; j++)
		{
			Chessman* chessman = mChessboard[i][j];
			if (chessman)
			{
				RemoveChessman(i+1, j+1);
			}
		}
	}
}

GameObject* Game::GetGameObjectByNode( Node* node )
{
	GameObjectList::iterator it = mGameObjects.begin();

	while (it != mGameObjects.end())
	{
		GameObject* obj = *it;
		if (obj->GetNode() == node)
		{
			return obj;
		}
		it++;
	}

	return NULL;
}

void Game::SelectChessman( Chessman* chessman )
{	
	if (chessman->GetOwner() == mCurrentPlayer)
	{
		if (mSelectedChessman != chessman)
		{
			if (mSelectedChessman)
			{
				mSelectedChessman->SetSelected(false);
			}
			chessman->SetSelected(true);
			mSelectedChessman = chessman;
		}
	}
}

void Game::MoveToPosition( int x, int y )
{
	if (mSelectedChessman == NULL)
	{
		return;
	}

	int chessX = mSelectedChessman->GetX();
	int chessY = mSelectedChessman->GetY();
	
	MoveList moveList = mSelectedChessman->GetLegalMoves(mChessboard);

	if (find(moveList.begin(), moveList.end(), Vector2(x, y)) != moveList.end())
	{
		int dist = abs(x - chessX) + abs(y - chessY);

		mChessboard[chessX-1][chessY-1] = NULL;
		mSelectedChessman->SetPosition(x, y);
		mChessboard[x-1][y-1] = mSelectedChessman;

		bool canMove = false;
		if (dist == 4)
		{
			RemoveChessman( (x+chessX)/2, (y+chessY)/2 );

			moveList = mSelectedChessman->GetLegalMoves(mChessboard);
			MoveList::iterator it = moveList.begin();
			while (it != moveList.end())
			{
				Vector2 move = *it;
				dist = abs(move.x - x) + (move.y - y);
				if (dist == 4) 
				{
					canMove = true;
					break;
				}
				it++;
			}
		}

		if (!canMove)
		{
			mSelectedChessman->SetSelected(false);
			mCurrentPlayer = !mCurrentPlayer;
			mSelectedChessman = NULL;
		}
	}
}

void Game::RemoveChessman( int x, int y )
{
	Chessman* chessman = GetChessmanAtPosition(x, y);

	if (chessman)
	{
		mChessboard[x-1][y-1] = NULL;
	}

	mGameObjects.erase(find(mGameObjects.begin(), mGameObjects.end(), chessman));
	delete chessman;
}
